We investigate the differences between the output given by the IDL software package "IMD" of David L. Windt, and the python package "TMM" of Steven J. Byrnes. The IMD software package is considered the reference by default. We aim to transition from IMD to TMM given that the latter is written in python and is open source.
References:
import funcs
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('presentation')
%matplotlib notebook
import warnings
warnings.simplefilter('ignore')
deg = np.pi/180. # conversion factor degrees to radians
# Define paths to data
workDir = '/Users/ioannisa/Desktop/python/miri_devel/'
nkDir = workDir+'nk/'
datapath = 'data/'
# initialize placeholders
wav = {'1A':np.linspace(4.8,5.8,10000),'1B':np.linspace(5.6,6.7,10000)}
n_ZnS,n_Si,n_BE,n_SiAs,n_Al = [{} for i in range(5)]
for band in wav.keys():
n_ZnS[band] = funcs.indexOfRefractionZnS(wav[band])
n_Si[band] = funcs.indexOfRefractionSi(wav[band])
n_BE[band] = funcs.indexOfRefractionBE(wav[band])
n_SiAs[band] = funcs.indexOfRefractionSiAs(wav[band])
n_Al[band] = funcs.indexOfRefractionAl(wav[band])
# load data
R,T,A = {},{},{}
for band in ['1A']:
R[band],T[band],A[band] = {},{},{}
#--(Incidence angle 0 deg) (vacuum - Si layer (465um))
wav[band],R[band]['00'],T[band]['00'],A[band]['00'] = np.loadtxt(datapath+band+'_SpecRes0micron_IncidenceAngle0deg_Si_layer.txt',unpack=True,usecols=(0,1,4,7),skiprows=14)
ignore,R[band]['01'],T[band]['01'],A[band]['01'] = np.loadtxt(datapath+band+'_SpecRes0.001micron_IncidenceAngle0deg_Si_layer.txt',unpack=True,usecols=(0,1,4,7),skiprows=14)
ignore,R[band]['02'],T[band]['02'],A[band]['02'] = np.loadtxt(datapath+band+'_SpecRes0.002micron_IncidenceAngle0deg_Si_layer.txt',unpack=True,usecols=(0,1,4,7),skiprows=14)
#--(Incidence angle 0 deg) (vacuum - ZnS layer (0.65um) - Si layer (465um))
ignore,R[band]['10'],T[band]['10'],A[band]['10'] = np.loadtxt(datapath+band+'_SpecRes0micron_IncidenceAngle0deg_withARcoat.txt',unpack=True,usecols=(0,1,2,3),skiprows=15)
ignore,R[band]['11'],T[band]['11'],A[band]['11'] = np.loadtxt(datapath+band+'_SpecRes0.001micron_IncidenceAngle0deg_withARcoat.txt',unpack=True,usecols=(0,1,2,3),skiprows=15)
ignore,R[band]['12'],T[band]['12'],A[band]['12'] = np.loadtxt(datapath+band+'_SpecRes0.002micron_IncidenceAngle0deg_withARcoat.txt',unpack=True,usecols=(0,1,2,3),skiprows=15)
#--(Incidence angle 0 deg) (vacuum - SiAs layer (35um))
ignore,R[band]['20'],T[band]['20'],A[band]['20'] = np.loadtxt(datapath+band+'_SpecRes0micron_IncidenceAngle0deg_SiAs_layer.txt',unpack=True,usecols=(0,1,4,7),skiprows=14)
ignore,R[band]['21'],T[band]['21'],A[band]['21'] = np.loadtxt(datapath+band+'_SpecRes0.001micron_IncidenceAngle0deg_SiAs_layer.txt',unpack=True,usecols=(0,1,4,7),skiprows=14)
ignore,R[band]['22'],T[band]['22'],A[band]['22'] = np.loadtxt(datapath+band+'_SpecRes0.002micron_IncidenceAngle0deg_SiAs_layer.txt',unpack=True,usecols=(0,1,4,7),skiprows=14)
#--(Incidence angle 0 deg) (vacuum - Si layer (465um) - SiAs layer (35um))
ignore,R[band]['30'],T[band]['30'],A[band]['30'] = np.loadtxt(datapath+band+'_SpecRes0micron_IncidenceAngle0deg_Si_layer_SiAs_layer.txt',unpack=True,usecols=(0,1,4,7),skiprows=15)
#--(Incidence angle 0 deg) (vacuum - ZnS layer (0.65um) - Si layer (465um) - SiAs layer (35um))
ignore,R[band]['40'],T[band]['40'],A[band]['40'] = np.loadtxt(datapath+band+'_SpecRes0micron_IncidenceAngle0deg_ZnS_layer_Si_layer_SiAs_layer.txt',unpack=True,usecols=(0,1,4,7),skiprows=16)
#--(Incidence angle 0 deg) (vacuum - ZnS layer (0.65um))
ignore,R[band]['50'],T[band]['50'],A[band]['50'] = np.loadtxt(datapath+band+'_SpecRes0micron_IncidenceAngle0deg_ZnS_layer.txt',unpack=True,usecols=(0,1,4,7),skiprows=14)
#--(Incidence angle 10 deg) (vacuum - ZnS layer (0.65um) - Si layer (465um) - SiAs layer (35um))
ignore,R[band]['60'],T[band]['60'],A[band]['60'] = np.loadtxt(datapath+band+'_SpecRes0micron_IncidenceAngle10deg_ZnS_layer_Si_layer_SiAs_layer.txt',unpack=True,usecols=(0,1,4,7),skiprows=16)
#--(Incidence angle 0 deg) (vacuum - ZnS layer (0.65um) - Si layer (465um, sigma 0.1um) - SiAs layer (35um))
ignore,R[band]['70'],T[band]['70'],A[band]['70'] = np.loadtxt(datapath+band+'_SpecRes0micron_IncidenceAngle0deg_ZnS_layer_Si_layerRoughness0.1um_SiAs_layer.txt',unpack=True,usecols=(0,1,4,7),skiprows=16)
#--(Incidence angle 0 deg) (vacuum - ZnS layer (0.65um) - Si layer (465um, sigma 0.1um) - SiAs layer (35um) - Al substrate)
ignore,R[band]['80'],T[band]['80'],A[band]['80'] = np.loadtxt(datapath+band+'_SpecRes0micron_IncidenceAngle0deg_ZnS_layer_Si_layer_SiAs_layer_Al_substrate.txt',unpack=True,usecols=(0,1,4,7),skiprows=17)
band = '1A'
Refl,Transm,Absorp = [np.zeros(len(wav[band])) for i in range(3)]
for i,wvl in enumerate(wav[band]):
# define stack of refractive layers
n_list = [1,n_Si[band][i], 1] # refractive index
d_list = [np.inf, 465e3, np.inf] # thickness, nanometers
lambda_vac = wvl*1000 # convert microns to nanometers
# solve the Fresnel equations using the Transfer-Matrix Method
Refl[i],Transm[i],Absorp[i] = funcs.simple_tmm(n_list, d_list, 0*deg, lambda_vac)
fig,axs = plt.subplots(2,1,figsize=(12,8))
axs[0].plot(wav[band],Transm,label='TMM')
axs[0].plot(wav[band],T[band]['00'],label='IMD')
axs[0].set_ylabel('Transmittance')
axs[0].legend(loc='upper right',fontsize=12)
axs[1].plot(wav[band],((Transm-T[band]['00'])/np.array(Transm))*100.)
axs[1].set_xlabel('Wavelength [micron]')
axs[1].set_ylabel('Percent difference [%]')
plt.tight_layout()
The output of the Windt IMD software and the Byrnes TMM python module agree down to the 0.002% level.
# simulate a finite instrumental resolution..
Delta_lambda = 0.001 # sigma, micron
convTransm = funcs.convolvegauss_windt(wav[band],Transm,Delta_lambda)
fig,axs = plt.subplots(2,1,figsize=(12,8))
axs[0].plot(wav[band],convTransm,label='TMM')
axs[0].plot(wav[band],T[band]['01'],label='IMD')
axs[0].set_ylabel('Convolved Transm.')
axs[0].legend(loc='upper right',fontsize=12)
axs[1].plot(wav[band],((convTransm-T[band]['01'])/convTransm)*100.)
axs[1].hlines(0,wav[band].min(),wav[band].max(),'k',linestyle='dashed')
axs[1].set_ylim(-0.001,0.001)
axs[1].set_xlabel('Wavelength [micron]')
axs[1].set_ylabel('Percent difference [%]')
plt.tight_layout()
band = '1A'
Refl,Transm,Absorp = [np.zeros(len(wav[band])) for i in range(3)]
for i,wvl in enumerate(wav[band]):
# define stack of refractive layers
n_list = [1,n_SiAs[band][i], 1] # refractive index
d_list = [np.inf, 35e3, np.inf] # thickness, nanometers
lambda_vac = wvl*1000 # convert microns to nanometers
# solve the Fresnel equations using the Transfer-Matrix Method
Refl[i],Transm[i],Absorp[i] = funcs.simple_tmm(n_list, d_list, 0*deg, lambda_vac)
fig,axs = plt.subplots(2,1,figsize=(12,8))
axs[0].plot(wav[band],Absorp,label='TMM')
axs[0].plot(wav[band],A[band]['20'],label='IMD')
axs[0].set_ylabel('Absorptance')
axs[0].legend(loc='upper right',fontsize=12)
axs[1].plot(wav[band],((Absorp-A[band]['20'])/Absorp)*100.)
axs[1].set_xlabel('Wavelength [micron]')
axs[1].set_ylabel('Percent difference [%]')
plt.tight_layout()
band = '1A'
Refl,Transm,Absorp = [np.zeros(len(wav[band])) for i in range(3)]
for i,wvl in enumerate(wav[band]):
# define stack of refractive layers
n_list = [1,n_ZnS[band][i], 1] # refractive index
d_list = [np.inf, 0.65e3, np.inf] # thickness, nanometers
lambda_vac = wvl*1000 # convert microns to nanometers
# solve the Fresnel equations using the Transfer-Matrix Method
Refl[i],Transm[i],Absorp[i] = funcs.simple_tmm(n_list, d_list, 0*deg, lambda_vac)
fig,axs = plt.subplots(2,1,figsize=(12,8))
axs[0].plot(wav[band],Refl,label='TMM')
axs[0].plot(wav[band],R[band]['50'],label='IMD')
axs[0].set_ylabel('Transmittance')
axs[0].legend(loc='upper right',fontsize=12)
axs[1].plot(wav[band],((Transm-T[band]['50'])/Transm)*100.)
axs[1].set_xlabel('Wavelength [micron]')
axs[1].set_ylabel('Percent difference [%]')
plt.tight_layout()
band = '1A'
Refl,Transm,Absorp = [np.zeros(len(wav[band])) for i in range(3)]
for i,wvl in enumerate(wav[band]):
# define stack of refractive layers
n_list = [1,n_Si[band][i],n_SiAs[band][i], 1] # refractive index
d_list = [np.inf, 465e3,35e3, np.inf] # thickness, nanometers
lambda_vac = wvl*1000 # convert microns to nanometers
# solve the Fresnel equations using the Transfer-Matrix Method
Refl[i],Transm[i],Absorp[i] = funcs.simple_tmm(n_list, d_list, 0*deg, lambda_vac)
fig,axs = plt.subplots(2,1,figsize=(12,8))
axs[0].plot(wav[band],Absorp,label='TMM')
axs[0].plot(wav[band],A[band]['30'],label='IMD')
axs[0].set_ylabel('Absorptance')
axs[0].legend(loc='upper right',fontsize=12)
axs[1].plot(wav[band],((Absorp-A[band]['30'])/Absorp)*100.)
axs[1].set_xlabel('Wavelength [micron]')
axs[1].set_ylabel('Percent difference [%]')
plt.tight_layout()
band = '1A'
Refl,Transm,Absorp = [np.zeros(len(wav[band])) for i in range(3)]
for i,wvl in enumerate(wav[band]):
# define stack of refractive layers
n_list = [1,n_ZnS[band][i],n_Si[band][i],n_SiAs[band][i], 1] # refractive index
d_list = [np.inf, 0.65e3,465e3,35e3, np.inf] # thickness, nanometers
lambda_vac = wvl*1000 # convert microns to nanometers
# solve the Fresnel equations using the Transfer-Matrix Method
Refl[i],Transm[i],Absorp[i] = funcs.simple_tmm(n_list, d_list, 0*deg, lambda_vac)
fig,axs = plt.subplots(2,1,figsize=(12,8))
axs[0].plot(wav[band],Absorp,label='TMM')
axs[0].plot(wav[band],A[band]['40'],label='IMD')
axs[0].set_ylabel('Absorptance')
axs[0].legend(loc='upper right',fontsize=12)
axs[1].plot(wav[band],((Absorp-A[band]['40'])/Absorp)*100.)
axs[1].set_ylim(-0.002,0.002)
axs[1].set_xlabel('Wavelength [micron]')
axs[1].set_ylabel('Percent difference [%]')
plt.tight_layout()
band = '1A'
Refl,Transm,Absorp = [np.zeros(len(wav[band])) for i in range(3)]
for i,wvl in enumerate(wav[band]):
# define stack of refractive layers
n_list = [1,n_ZnS[band][i],n_Si[band][i],n_SiAs[band][i], 1] # refractive index
d_list = [np.inf, 0.65e3,465e3,35e3, np.inf] # thickness, nanometers
lambda_vac = wvl*1000 # convert microns to nanometers
# solve the Fresnel equations using the Transfer-Matrix Method
Refl[i],Transm[i],Absorp[i] = funcs.simple_tmm(n_list, d_list, 10*deg, lambda_vac)
fig,axs = plt.subplots(2,1,figsize=(12,8))
axs[0].plot(wav[band],Absorp,label='TMM')
axs[0].plot(wav[band],A[band]['60'],label='IMD')
axs[0].set_ylabel('Absorptance')
axs[0].legend(loc='upper right',fontsize=12)
axs[1].plot(wav[band],((Absorp-A[band]['60'])/Absorp)*100.)
axs[1].set_ylim(-0.002,0.002)
axs[1].set_xlabel('Wavelength [micron]')
axs[1].set_ylabel('Percent difference [%]')
plt.tight_layout()
band = '1A'
Refl,Transm,Absorp = [np.zeros(len(wav[band])) for i in range(3)]
for i,wvl in enumerate(wav[band]):
# define stack of refractive layers
n_list = [1,n_ZnS[band][i],n_Si[band][i],n_SiAs[band][i], 1] # refractive index
d_list = [np.inf, 0.65e3,465e3,35e3, np.inf] # thickness, nanometers
sig_list = [0,0,0.01,0,0]
lambda_vac = wvl*1000 # convert microns to nanometers
# solve the Fresnel equations using the Transfer-Matrix Method
Refl[i],Transm[i],Absorp[i] = funcs.not_simple_tmm(n_list, d_list, sig_list, 0*deg, lambda_vac)
fig,axs = plt.subplots(2,1,figsize=(12,8))
axs[0].plot(wav[band],Absorp,label='TMM')
axs[0].plot(wav[band],A[band]['70'],label='IMD')
axs[0].set_ylabel('Absorptance')
axs[0].legend(loc='upper right',fontsize=12)
axs[1].plot(wav[band],((Absorp-A[band]['70'])/Absorp)*100.)
# axs[1].set_ylim(-0.002,0.002)
axs[1].set_xlabel('Wavelength [micron]')
axs[1].set_ylabel('Percent difference [%]')
plt.tight_layout()
band = '1A'
Refl,Transm,Absorp = [np.zeros(len(wav[band])) for i in range(3)]
for i,wvl in enumerate(wav[band]):
# define stack of refractive layers
n_list = [1,n_ZnS[band][i],n_Si[band][i],n_SiAs[band][i], n_Al[band][i]] # refractive index
d_list = [np.inf, 0.65e3,465e3,35e3, np.inf] # thickness, nanometers
lambda_vac = wvl*1000 # convert microns to nanometers
# solve the Fresnel equations using the Transfer-Matrix Method
Refl[i],Transm[i],Absorp[i] = funcs.simple_tmm(n_list, d_list, 0*deg, lambda_vac)
fig,axs = plt.subplots(2,1,figsize=(12,8))
axs[0].plot(wav[band],Absorp,label='TMM')
axs[0].plot(wav[band],A[band]['80'],label='IMD')
axs[0].set_ylabel('Absorptance')
axs[0].legend(loc='upper right',fontsize=12)
axs[1].plot(wav[band],((Absorp-A[band]['80'])/Absorp)*100.)
axs[1].set_ylim(-0.004,0.004)
axs[1].set_xlabel('Wavelength [micron]')
axs[1].set_ylabel('Percent difference [%]')
plt.tight_layout()